package com.toy.base.service.impl;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.toy.base.dao.UserDAO;
import com.toy.base.domain.User;
import com.toy.base.service.UserManager;
import com.toy.core.cache.annotation.CachePackage;
import com.toy.core.cache.annotation.CachePutGet;
import com.toy.core.dao.MongoCrudRepository;
import com.toy.core.security.exception.AuthenticationException;
import com.toy.core.security.userdetails.UserDetail;
import com.toy.core.security.userdetails.UserDetailsImpl;
import com.toy.core.security.userdetails.UserDetailsService;
import com.toy.core.service.impl.BaseManagerImpl;

@Service("userManager")
@CachePackage(User.class)
public class UserManagerImpl extends BaseManagerImpl<User> implements UserManager,UserDetailsService {
	
	@Autowired
	private UserDAO userDAO;
	
	public MongoCrudRepository<User,Long> getMongoCrudRepository() {
		return userDAO;
	}
	
	@CachePutGet
	public UserDetail getByUsername(String username)
			throws AuthenticationException {
		User user = userDAO.getUniqueByProperty("username", username);
		if ( user == null ){
			throw new AuthenticationException(AuthenticationException.CODE_UsernameNotFoundException);
		}
		return new UserDetailsImpl(username,user.getPassword(),false,false,false,false,null);
	}
	
	@CachePutGet
	public UserDetail validate(String username, String password)
			throws AuthenticationException {
		if (StringUtils.isBlank(username)){
			throw new AuthenticationException(AuthenticationException.CODE_UsernameNotFoundException);
		}
		if (StringUtils.isBlank(password)){
			throw new AuthenticationException(AuthenticationException.CODE_BadCredentialsException);
		}
		User user = userDAO.getUniqueByProperty("username", username);
		if ( user == null ){
			throw new AuthenticationException(AuthenticationException.CODE_UsernameNotFoundException);
		}
		if ( !password.equals(user.getPassword())){
			throw new AuthenticationException(AuthenticationException.CODE_BadCredentialsException);
		}
		return new UserDetailsImpl(username,user.getPassword(),false,false,false,false,null);
	}
	
	@CachePutGet
	public User getUserByUsername(String username) {
		return userDAO.getUniqueByProperty("username", username);
	}
	
	@CachePutGet
	public Map<Long, User> findByUserIds(Collection<?> c) {
		List<Criteria> criterions = Lists.newArrayList();
		criterions.add(Criteria.where("id").in(c));
		List<User> users = userDAO.findByCriteria(criterions);
		Map<Long, User> result = Maps.newHashMap();
		for (User user : users) {
			result.put(user.getId(), user);
		}
		return result;
	}
}
